/*************************************************************************
   > File Name: file.go
   > Author: Kee
   > Mail: chinboy2012@gmail.com
   > Created Time: 2017.11.29
************************************************************************/
package util

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

const (
	APPEND = 1
)

func Get(file string) (string, error) {
	fl, err := os.Open(file)

	if err != nil {
		return "", err
	}

	defer fl.Close()

	content, err := ioutil.ReadAll(fl)

	return string(content), err
}

func putFile(file string, content string, opt int) (bool, error) {
	if true != Exists(file) {
		_, err := os.Create(file)

		if err != nil {
			return false, err
		}
	}

	opts := 0

	if opt == APPEND {
		opts = os.O_APPEND | os.O_WRONLY
	} else {
		opts = os.O_WRONLY
	}

	fl, err := os.OpenFile(file, opts, 0755)

	n, err := io.WriteString(fl, content)
	defer fl.Close()

	if err != nil {
		return false, err
	}
	return bool(n > len(content)), err
}

func Put(file string, content string) (bool, error) {
	return putFile(file, content, 0)
}

func Append(file string, content string) (bool, error) {
	return putFile(file, content, APPEND)
}

func Exists(file string) bool {
	if _, err := os.Stat(file); os.IsNotExist(err) {
		return false
	}
	return true
}

func FindFile(fileName string) ([]string, error) {
	pattern := fileName

	if strings.Index(fileName, "*") != -1 {
		fileName, pattern = getPattern(fileName)
	}

	var list []string

	file, err := os.Open(fileName)
	if err != nil {
		return nil, err
	}

	fi, err := file.Stat()
	if err != nil {
		return nil, err
	}

	if !fi.IsDir() {
		list = append(list, fileName)
		return list, nil
	}

	reg := regexp.MustCompile(pattern)

	// 遍历目录
	filepath.Walk(fileName,
		func(path string, f os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			if f.IsDir() {
				path = filepath.ToSlash(path)
				if !strings.HasSuffix(path, "/") {
					path += "/"
				}
				return nil
			}
			// 匹配目录
			pAName := strings.Replace(path, fileName, "", -1)
			matched := reg.MatchString(pAName)
			if matched {
				pflag := true
				match_maps := reg.FindAllStringSubmatch(pAName, -1)
				for k, mms := range match_maps[0] {
					if k <= 0 {
						continue
					}
					smm := fmt.Sprintf("%v", mms)

					if strings.Index(string(smm), "/") != -1 {
						pflag = false
					}
				}
				if pflag == true {
					list = append(list, path)
				}
			}
			return nil
		})

	return list, nil
}

func getPattern(fileName string) (string, string) {
	part_1 := strings.Index(fileName, "*")
	fn_1 := substr(fileName, 0, part_1)

	part_2 := strings.LastIndex(fn_1, "/") + 1
	fn_2 := substr(fn_1, 0, part_2)

	fn_2_last := substr(fn_1, part_2, len(fn_2))

	fn_last := substr(fileName, part_1, len(fileName))

	pattern := fn_2_last + fn_last
	fileName = fn_2

	if strings.Index(pattern, ".") != -1 {
		pattern = strings.Replace(pattern, ".", `\.`, -1)
	}

	pattern = strings.Replace(pattern, "*", `(.*)`, -1)
	pattern = "^" + pattern + "$"
	pattern = "(?U)" + pattern

	return fileName, pattern
}

func substr(s string, pos, length int) string {
	runes := []rune(s)
	l := pos + length
	if l > len(runes) {
		l = len(runes)
	}
	return string(runes[pos:l])
}
